#include "FaceFile.h"
#include <math.h>
#include<fstream>

FaceFile::FaceFile()
{

}


FaceFile::~FaceFile()
{

}

float GetMold(const std::vector<float>& vec)
{
	int n = vec.size();
	float sum = 0.0;
	for (int i = 0; i < n; ++i)sum += vec[i] * vec[i];
	return sqrt(sum);
};

void FaceFile::Add(std::vector<float> & features, long id)
{
	FaceInfo info;
	info.features = features;
	info.id = id;
	save_data.push_back(std::move(info));
}

void FaceFile::Add(std::vector<float> && features, long id)
{
	FaceInfo info;
	info.features = std::move(features);
	info.id = id;
	save_data.push_back(std::move(info));
}

std::list<FaceInfo>&& FaceFile::MoveList()
{
	return std::move(save_data);
}

bool FaceFile::Save(std::string save_to, unsigned int version)
{
	//检测版本 
	if (!HasVer(version))return false;
	//检测后缀
	int loc = save_to.find_last_of('.');
	std::fstream save;
	if (loc == -1 || save_to.substr(loc) != ".facedata")
		save.open(save_to + ".facedata", std::ios::out | std::ios::binary);
	else
		save.open(save_to, std::ios::out | std::ios::binary);
	if (!save.is_open())return false;
	//buffer🔝
	char buffer[sizeof(unsigned int)];
	//写入校验位
	buffer[0] = 'F';
	save.write(buffer, sizeof(char));
	//写入版本
	*((unsigned int*)buffer) = version;
	save.write(buffer, sizeof(unsigned int));
	//记录变量 
	bool res = false;
	//选择版本
	switch (version)
	{
	case Version(1, 0):
		res = SaveVer1_0(save);
		break;
	default:
		break;
	}
	save.close();
	if (res == false)std::remove((save_to + ".facedata").c_str());
	return res;
}

bool FaceFile::Load(std::string path)
{
	//检测文件
	int loc = path.find_last_of('.');
	if (loc == -1)return false;
	if (path.substr(loc) != ".facedata")return false;
	std::fstream save;
	save.open(path, std::ios::in | std::ios::binary);
	if (!save.is_open())return false;
	//读出校验位
	char ch;
	save.read(&ch, sizeof(char));
	if (ch != 'F')
	{
		save.close();
		return false;
	}
	//读出版本
	unsigned int version = 0;
	save.read((char*)&version, sizeof(unsigned int));
	//记录变量 
	bool res = false;
	//选择版本
	switch (version)
	{
	case Version(1, 0):
		res = LoadVer1_0(save);
		break;
	default:
		save.close();
		return false;
	}
	save.close();
	return res;
}

bool FaceFile::HasVer(unsigned int version)
{
	switch (version)
	{
	case Version(1, 0):
		return true;
	}
	return false;
}

bool FaceFile::SaveVer1_0(std::fstream & save)
{
	const int buffer_size = 256;
	char buffer[buffer_size];
	//二次校验位
	buffer[0] = 'f';
	buffer[1] = 'a';
	buffer[2] = 'c';
	buffer[3] = 'e';
	save.write(buffer, sizeof(char) * 4);
	//记录特征值个数
	*((unsigned int*)buffer) = save_data.size();
	save.write(buffer, sizeof(unsigned int));
	//开始记录
	for (auto & item : save_data)
	{
		//记录特征值个数
		*((unsigned int*)buffer) = item.features.size();
		save.write(buffer, sizeof(unsigned int));
		//记录id
		*((long*)buffer) = item.id;
		save.write(buffer, sizeof(unsigned int));
		//记录特征值
		int i = 0;
		for (auto & f : item.features)
		{
			((float*)buffer)[i] = f;
			i++;
			if (i >= buffer_size / sizeof(float))
			{
				save.write(buffer, i * sizeof(float));
				i = 0;
			}
		}
		save.write(buffer, i * sizeof(float));
	}
	return true;
}

bool FaceFile::LoadVer1_0(std::fstream & save)
{
	const int buffer_size = 256;
	char buffer[buffer_size];
	//检验校验
	save.read(buffer, sizeof(char) * 4);
	if (
		buffer[0] != 'f' ||
		buffer[1] != 'a' ||
		buffer[2] != 'c' ||
		buffer[3] != 'e'
		)return false;
	//读出特征值个数
	unsigned int count = 0;
	save.read((char*)&count, sizeof(unsigned int));
	//读出数据
	for (int i = 0; i < count; i++)
	{
		FaceInfo info;
		unsigned int n = 0;
		//读出特征值个数
		save.read((char*)&n, sizeof(unsigned int));
		//读出id
		save.read((char*)&info.id, sizeof(unsigned int));
		//读出特征值
		unsigned int max_data = buffer_size / sizeof(float);
		while (1)
		{
			if (max_data <= n)
			{
				n = n - max_data;
			}
			else
			{
				max_data = n;
				n = 0;
			}
			save.read(buffer, max_data * sizeof(float));
			for (int k = 0; k < max_data; k++)info.features.push_back(((float*)buffer)[k]);
			if (n == 0)break;
		}
		save_data.push_back(std::move(info));
	}
	return true;
}
